﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using OpenTK;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.Common;
using OpenTK.Graphics.OpenGL;
using OpenTK.Mathematics;

namespace OpenTK_Demo
{

    class Game : GameWindow
    {

        private int vertexBuffHandle;       //顶点缓存句柄
        private int shaderProgramHandle;    //shader程序句柄
        private int vertexArrayHandle;      //顶点列表句柄   VAO句柄

        public Game(int width = 1920, int height = 1080, string title = "GAME1")
            : base(
                  GameWindowSettings.Default,
                  new NativeWindowSettings()
                  {
                      Title = title,
                      Size = new Vector2i(width, height),
                      WindowBorder = WindowBorder.Fixed,
                      StartVisible = false,
                      StartFocused = true,
                      API = ContextAPI.OpenGL,
                      Profile = ContextProfile.Core,
                      APIVersion = new Version(3, 3),
                  })
        {
            this.CenterWindow();
        }

        /// <summary>
        /// 窗口重调整代码
        /// </summary>
        /// <param name="e"></param>
        protected override void OnResize(ResizeEventArgs e)
        {
            GL.Viewport(0, 0, e.Width, e.Height);
            base.OnResize(e);
        }

        /// <summary>
        /// 加载时运行
        /// </summary>
        protected override void OnLoad()
        {
            this.IsVisible = true;

            GL.ClearColor(Color4.AliceBlue);
            //构建三角形的点集
            float[] vertices = new float[] {
                0.0f,-0.5f,0.0f,   1.0f,0.0f,0.0f,  1.0f,
                0.5f,-0.0f,0.0f,   0.0f,1.0f,0.0f,  1.0f,
                -0.0f,0.5f,0.0f,   0.0f,0.0f,1.0f,  1.0f,
            };


            this.vertexBuffHandle = GL.GenBuffer();//建立一个顶点缓存句柄
            GL.BindBuffer(BufferTarget.ArrayBuffer, this.vertexBuffHandle);//将顶点缓存句柄绑定在缓存实例
            GL.BufferData(BufferTarget.ArrayBuffer,
                vertices.Length * sizeof(float),
                vertices, BufferUsageHint.StaticDraw);  //将顶点位置放入缓存实例
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);


            this.vertexArrayHandle = GL.GenVertexArray();       //顶点列表VAO
            GL.BindVertexArray(this.vertexArrayHandle);         //VAO句柄绑定进入GL状态机

            GL.BindBuffer(BufferTarget.ArrayBuffer, this.vertexBuffHandle);
            GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 7 * sizeof(float), 0);                   //VAO读取VBO数据的方式 0 为组号  offset表述在每段内读取的开始位
            GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, 7 * sizeof(float), 3 * sizeof(float));   //VAO读取VBO数据的方式 1 为组号  offset表述在每段内读取的开始位
            GL.EnableVertexAttribArray(0);  //上述定义的防止顶点的缓存组  组号0
            GL.EnableVertexAttribArray(1);  //上述定义的防止顶点的缓存组  组号1 

            GL.BindVertexArray(0);

            //shader代码 
            string vertexShaderCode = Service.GetShaderCode().First();
            string pixelShaderCode  = Service.GetShaderCode().Last();
            //shader程序建立
            int vertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
            GL.ShaderSource(vertexShaderHandle, vertexShaderCode);
            GL.CompileShader(vertexShaderHandle);

            int pixelShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
            GL.ShaderSource(pixelShaderHandle, pixelShaderCode);
            GL.CompileShader(pixelShaderHandle);

            //生成shader程序
            this.shaderProgramHandle = GL.CreateProgram();
            //对shader程序 加载shader句柄
            GL.AttachShader(this.shaderProgramHandle, vertexShaderHandle);
            GL.AttachShader(this.shaderProgramHandle, pixelShaderHandle);
            //链接shader程序
            GL.LinkProgram(this.shaderProgramHandle);

            //卸载句柄
            GL.DetachShader(this.shaderProgramHandle, vertexShaderHandle);
            GL.DetachShader(this.shaderProgramHandle, pixelShaderHandle);

            //清空缓存
            GL.DeleteShader(vertexShaderHandle);
            GL.DeleteShader(pixelShaderHandle);

            base.OnLoad();
        }

        protected override void OnUnload()
        {
            GL.BindVertexArray(0);
            GL.DeleteVertexArray(this.vertexArrayHandle);

            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
            GL.DeleteBuffer(this.vertexBuffHandle);

            GL.UseProgram(0);
            GL.DeleteProgram(this.shaderProgramHandle);

            base.OnUnload();
        }

        protected override void OnUpdateFrame(FrameEventArgs args)
        { 
            base.OnUpdateFrame(args);
        }

        protected override void OnRenderFrame(FrameEventArgs args)
        {
            //GL.ClearColor(new Color4(0.3f, 0.4f, 0.6f, 1.0f));
            GL.Clear(ClearBufferMask.ColorBufferBit);

            GL.UseProgram(this.shaderProgramHandle);
            GL.BindVertexArray(this.vertexArrayHandle);


            GL.DrawArrays(PrimitiveType.Triangles, 0, 3);

            this.Context.SwapBuffers();

            //base.OnRenderFrame(args);

            base.OnRenderFrame(args);
        }

    }
}
